import { Subject, Subscription } from 'rxjs';
import { Tools } from './tools';
/**
 * @description 拖拽事件类
 * @author zengwe
 * @date 2019/09/10
 */
export class Drag {
    public move: Subject<{position:IPosition, startEle: HTMLElement, evt: {down: MouseEvent, move: MouseEvent}}> = new Subject();
    protected moveFunc: any;
    protected mouseupFunc: any;
    protected mousedownFunc: any;
    protected mouseleaveFunc: any;
    protected tempData: ITempData;
    protected moveSub: Subscription;
    constructor(private ele: HTMLElement,private getOriginEle: {():HTMLElement} = null, isDefaultDrag: boolean = false)  {
        this.mouseupFunc = this.mouseup.bind(this);
        this.mousedownFunc = this.mousedown.bind(this);
        this.mouseleaveFunc = this.mouseleave.bind(this);
        this.bindEvent();
        if(isDefaultDrag ==  true) {
            this.moveSub = this.move.subscribe(res => {
                let style = Tools.styleToObj(res.startEle.getAttribute('style'));
                if(style.top == undefined) {
                  style.top = 0;
                }else{
                  style.top = Number(style.top.replace('px', ''));
                }
                if(style.left == undefined) {
                  style.left = 0;
                }else{
                  style.left =  Number(style.left.replace('px', ''));
                }
                if(style.position == undefined) {
                  style.position = 'relative';
                }
                style.top = String(style.top + res.position.y) + 'px';
                style.left = String(style.left + res.position.x) + 'px';
                getOriginEle().setAttribute('style',Tools.objToStyle(style))
            });
        }
    }
    protected bindEvent() {
        this.ele.addEventListener('mousedown', this.mousedownFunc);
        document.addEventListener('mouseup', this.mouseupFunc);
        document.addEventListener('mouseleave', this.mouseleaveFunc);
    }
    protected mousedown(evt: MouseEvent) {
        this.tempData = this.resetTempData();
        // if(this.getOriginEle == null) {
        //   this.tempData.originEle = <HTMLElement>this.ele.cloneNode(true);  
        // }else{
            
        // }
        this.tempData.originEle = <HTMLElement>this.getOriginEle().cloneNode(true);
        this.tempData.mousedownEvt = evt;
        if(this.moveFunc == undefined) {
           this.moveFunc = this.mousemove.bind(this); 
        }
        document.removeEventListener('mousemove', this.moveFunc);
        document.addEventListener('mousemove', this.moveFunc);
    }
    protected mousemove(evt: MouseEvent) {
        let x = evt.screenX - this.tempData.mousedownEvt.screenX;
        let y = evt.screenY - this.tempData.mousedownEvt.screenY;
        this.move.next({position: {x: x, y: y}, startEle: this.tempData.originEle, evt: {down: this.tempData.mousedownEvt, move: evt}});
    }
    protected mouseleave(evt: MouseEvent) {
        document.removeEventListener('mousemove', this.moveFunc);
    }
    protected mouseup(evt: MouseEvent) {
        document.removeEventListener('mousemove', this.moveFunc);
    }
    protected resetTempData() {
        let tempdata:ITempData  = {originEle: null, styleObj: {}, mousedownEvt: null};
        Object.defineProperties(tempdata, {
            originEle: {
                value: null
            },
            styleObj: {
                get: () => {
                    if((<any>tempdata)._styleObj != null) {
                        return (<any>tempdata)._styleObj;
                    } 
                    let styleStr = tempdata.originEle.getAttribute('style');
                    let obj = Tools.styleToObj(styleStr);
                    (<any>tempdata)._styleObj = obj;
                    return (<any>tempdata)._styleObj;
                },
                set: (val: {[key: string]: any}) => {
                    (<any>tempdata)._styleObj = val;
                }
            },
            _styleObj: {
                value: null,
                enumerable: false
            },
            mousedownEvt: {
                value: null
            }
        });
        return tempdata;
    }
    public destroy() {
        document.removeEventListener('mousemove', this.moveFunc);
        this.ele.removeEventListener('mousedown', this.mousedownFunc);
        document.removeEventListener('mouseup', this.mouseupFunc);
        document.removeEventListener('mouseleave', this.mouseleaveFunc);
        this.move.complete();
        this.move = undefined;
        try {
            this.moveSub.unsubscribe();
        } catch (error) {
            
        }
    }
}
interface IPosition {
    x: number;
    y: number;
}
interface ITempData {
    originEle: HTMLElement;
    styleObj: {[key:string]: any};
    mousedownEvt: MouseEvent;
}